﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Cinch;
using System.ComponentModel;
using System.ComponentModel.Composition;
using System.Configuration;
using System.Windows.Data;

namespace Anata.Client
{
    /// <summary>
    /// </summary>
    public class TransaksiPembayaranViewModel : EditableValidatingViewModelBase
    {
        #region Data
        private ViewMode currentViewMode = ViewMode.AddMode;

		#region Data.Primitives
        private DataWrapper<Int32> idTransaksiPembayaran;
        private DataWrapper<Int32?> idTransaksi;
        private DataWrapper<Int32?> idJenisPembayaran;
        private String namaJenisPembayaran;
        private DataWrapper<Int32> nominalPembayaran;



        private bool isBusy = false;
        private int? previousIdJenisPembayaran;
        #endregion

        private IEnumerable<DataWrapperBase> cachedListOfDataWrappers;

        #region Data.Rules
		#endregion

		#region Data.VMs
		#endregion

        #region Data.References
        private bool isAllJenisPembayaranLoaded = false;
        private int pageJenisPembayaranLoaded = 0;
        private List<JenisPembayaran> jenisPembayarans;
        private ICollectionView jenisPembayaransCV;
        #endregion
        
        #region Data.Services
        private IMessageBoxService messageBoxService;
        private IUIVisualizerService uiVisualizerService;
        private IReferenceProvider referenceProvider;
		#endregion
        #endregion

        #region Constructor
        [ImportingConstructor]
        public TransaksiPembayaranViewModel(
            IMessageBoxService messageBoxService,
            IUIVisualizerService uiVisualizerService,
            IReferenceProvider referenceProvider)
        {
			#region Constructor.SetupServices
            this.messageBoxService = messageBoxService;
            this.uiVisualizerService = uiVisualizerService;
            this.referenceProvider = referenceProvider;
			#endregion

			#region Constructor.SetupCommands
            TransaksiPembayaranCancelCommand = new SimpleCommand<Object, Object>(CanExecuteTransaksiPembayaranCancelCommand, ExecuteTransaksiPembayaranCancelCommand);
            #endregion

            #region Constructor.SetupDataWrappers
            IdTransaksiPembayaran = new DataWrapper<Int32>(this, idTransaksiPembayaranChangeArgs);
            IdTransaksiPembayaran.IsEditable = true;
            IdTransaksi = new DataWrapper<Int32?>(this, idTransaksiChangeArgs);
            IdTransaksi.IsEditable = true;
            IdJenisPembayaran = new DataWrapper<Int32?>(this, idJenisPembayaranChangeArgs);
            IdJenisPembayaran.IsEditable = true;
            NominalPembayaran = new DataWrapper<Int32>(this, nominalPembayaranChangeArgs, NominalPembayaranChangeCallback);
            NominalPembayaran.IsEditable = true;
            #endregion

            //fetch list of all DataWrappers, so they can be used again later without the
            //need for reflection
            cachedListOfDataWrappers =
                DataWrapperHelper.GetWrapperProperties<TransaksiPembayaranViewModel>(this);

            #region Constructor.SetupValidationRules
            #endregion
			
			#region Constructor.SetupVMs
			#endregion

            id_created = ++num_created;
            #region Constructor.SetupReferences
            jenisPembayarans = new List<JenisPembayaran>();
            JenisPembayaransCV = CollectionViewSource.GetDefaultView(jenisPembayarans);
            LoadJenisPembayaran();
            #endregion
        }
        #endregion


        #region Static
        static TransaksiPembayaranViewModel()
        {

        }
        private int id_created = 0;
        static private int num_created = 0;

        #endregion

        #region Public Properties
        //commands
		#region Public.Commands
        public SimpleCommand<Object, Object> TransaksiPembayaranCancelCommand { get; private set; }
        #endregion

		#region Public.ViewMode
        /// <summary>
        /// The current ViewMode, when changed will loop
        /// through all nested DataWrapper objects and change
        /// their state also
        /// </summary>

        static PropertyChangedEventArgs currentViewModeChangeArgs =
            ObservableHelper.CreateArgs<TransaksiViewModel>(x => x.CurrentViewMode);

        public ViewMode CurrentViewMode
        {
            get { return currentViewMode; }
            set
            {
                currentViewMode = value;

                switch (currentViewMode)
                {
                    case ViewMode.AddMode:
                        //Quantity.DataValue= 0;
                        this.DisplayName = "Transaksi Baru";
                        break;
                    case ViewMode.EditMode:
                        this.DisplayName = "Ubah Transaksi";
                        break;
                    case ViewMode.ViewOnlyMode:
                        this.DisplayName = "Lihat Transaksi";
                        break;
                }

                //Now change all the CachedListOfDataWrappers
                //Which sets all the Cinch.DataWrapper<T>s to the correct IsEditable
                //state based on the new ViewMode applied to the ViewModel
                //we can use the Cinch.DataWrapperHelper class for this
                DataWrapperHelper.SetMode(
                    CachedListOfDataWrappers,
                    currentViewMode);

                NotifyPropertyChanged(currentViewModeChangeArgs);
            }
        }
		#endregion
        
		#region Public.Data
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs idTransaksiPembayaranChangeArgs =
            ObservableHelper.CreateArgs<TransaksiPembayaranViewModel>(x => x.IdTransaksiPembayaran);
        public DataWrapper<Int32> IdTransaksiPembayaran
        {
            get { return idTransaksiPembayaran; }
            set
            {
                idTransaksiPembayaran = value;
                NotifyPropertyChanged(idTransaksiPembayaranChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs idTransaksiChangeArgs =
            ObservableHelper.CreateArgs<TransaksiPembayaranViewModel>(x => x.IdTransaksi);
        public DataWrapper<Int32?> IdTransaksi
        {
            get { return idTransaksi; }
            set
            {
                idTransaksi = value;
                NotifyPropertyChanged(idTransaksiChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs idJenisPembayaranChangeArgs =
            ObservableHelper.CreateArgs<TransaksiPembayaranViewModel>(x => x.IdJenisPembayaran);
        public DataWrapper<Int32?> IdJenisPembayaran
        {
            get { return idJenisPembayaran; }
            set
            {
                idJenisPembayaran = value;
                NotifyPropertyChanged(idJenisPembayaranChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs namaJenisPembayaranChangeArgs =
            ObservableHelper.CreateArgs<TransaksiPembayaranViewModel>(x => x.NamaJenisPembayaran);
        public String NamaJenisPembayaran
        {
            get { return namaJenisPembayaran; }
            set
            {
                namaJenisPembayaran = value;
                NotifyPropertyChanged(namaJenisPembayaranChangeArgs);
            }
        }
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs nominalPembayaranChangeArgs =
            ObservableHelper.CreateArgs<TransaksiPembayaranViewModel>(x => x.NominalPembayaran);
        public DataWrapper<Int32> NominalPembayaran
        {
            get { return nominalPembayaran; }
            set
            {
                nominalPembayaran = value;
                NotifyPropertyChanged(nominalPembayaranChangeArgs);
            }
        }
        #endregion

        #region Public.IsBusy & Previouses
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs previousIdJenisPembayaranChangeArgs =
            ObservableHelper.CreateArgs<TransaksiPembayaranViewModel>(x => x.PreviousIdJenisPembayaran);
        public int? PreviousIdJenisPembayaran
        {
            get { return previousIdJenisPembayaran; }
            set
            {
                previousIdJenisPembayaran = value;
                NotifyPropertyChanged(previousIdJenisPembayaranChangeArgs);
            }
        }

        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs isBusyChangeArgs =
            ObservableHelper.CreateArgs<TransaksiPembayaranViewModel>(x => x.IsBusy);
        public bool IsBusy
        {
            get { return isBusy; }
            set
            {
                isBusy = value;
                NotifyPropertyChanged(isBusyChangeArgs);
            }
        }
        #endregion

        #region Public.CachedCollection
        /// <summary>
        /// Returns cached collection of DataWrapperBase
        /// </summary>
        public IEnumerable<DataWrapperBase> CachedListOfDataWrappers
        {
            get { return cachedListOfDataWrappers; }
        }
        #endregion

        #region Public.References
        /// <summary>
        /// </summary>
        static PropertyChangedEventArgs jenisPembayaransCVChangeArgs =
            ObservableHelper.CreateArgs<TransaksiPembayaranViewModel>(x => x.JenisPembayaransCV);
        public ICollectionView JenisPembayaransCV
        {
            get { return jenisPembayaransCV; }
            set
            {
                jenisPembayaransCV = value;
                NotifyPropertyChanged(jenisPembayaransCVChangeArgs);
            }
        }
        #endregion

        #region Public.DataVMs
        #endregion

        #endregion

        #region Command Handlers
        /// <summary>
        /// </summary>
        private bool CanExecuteTransaksiPembayaranCancelCommand(Object args)
        {
            return !isBusy && CurrentViewMode != ViewMode.ViewOnlyMode;
        }
        /// <summary>
        /// </summary>
        private void ExecuteTransaksiPembayaranCancelCommand(Object args)
        {
            Mediator.Instance.NotifyColleagues("TryRemoveTransaksiPembayaran", this);
        }
        #endregion

        #region Change Callbacks
        /// <summary>
        /// </summary>
        private void NominalPembayaranChangeCallback()
        {
            Mediator.Instance.NotifyColleagues<Boolean>("SummaryChangeMessage", true);
        }
        #endregion

        #region Private Methods
        #region PrivateMethods.Loader
        /// <summary>
        /// loader
        /// </summary>
        private void LoadJenisPembayaran()
        {
            referenceProvider.LazyFetchJenisPembayarans(pageJenisPembayaranLoaded, PostLoadJenisPembayaran);
        }

        /// <summary>
        /// post loader
        /// </summary>
        private void PostLoadJenisPembayaran(List<JenisPembayaran> dbJenisPembayaran)
        {
            //rekursif sampai semua diload
            int pageSize = Int32.Parse(ConfigurationManager.AppSettings["LazyLoadPageSize"].ToString());
            foreach (JenisPembayaran item in dbJenisPembayaran)
            {
                jenisPembayarans.Add(item);
            }

            if (dbJenisPembayaran.Count != pageSize)
            {
                //basis
                //sudah habis, done loading
                isAllJenisPembayaranLoaded = true;
                idJenisPembayaran.DataValue = previousIdJenisPembayaran;
            }
            else
            {
                //rekurens
                ++pageJenisPembayaranLoaded;
                LoadJenisPembayaran();
            }
        }
        #endregion
        #endregion

        #region Overrides

        static PropertyChangedEventArgs isValidChangeArgs =
            ObservableHelper.CreateArgs<TransaksiViewModel>(x => x.IsValid);

        public override bool IsValid
        {
            get
            {
                //return base.IsValid and use DataWrapperHelper, if you are
                //using DataWrappers
                return base.IsValid &&
                    DataWrapperHelper.AllValid(cachedListOfDataWrappers);
            }

        }

        public bool IsDirty
        {
            get
            {
                return DataWrapperHelper2.SomeDirty(cachedListOfDataWrappers);
            }
        }

        public override string ToString()
        {
            return String.Format("TransaksiViewModel {0}", this.idTransaksi);
        }
        #endregion

        #region EditableValidatingViewModelBase overrides
        protected override void OnBeginEdit()
        {
            base.OnBeginEdit();
            //Now walk the list of properties in the OrderViewModel
            //and call BeginEdit() on all Cinch.DataWrapper<T>s.
            //we can use the Cinch.DataWrapperHelper class for this
            DataWrapperHelper.SetBeginEdit(cachedListOfDataWrappers);
        }

        /// <summary>
        /// Override hook which allows us to also put any child 
        /// EditableValidatingViewModelBase objects into the EndEdit state
        /// </summary>
        protected override void OnEndEdit()
        {
            base.OnEndEdit();
            //Now walk the list of properties in the OrderViewModel
            //and call CancelEdit() on all Cinch.DataWrapper<T>s.
            //we can use the Cinch.DataWrapperHelper class for this
            DataWrapperHelper.SetEndEdit(cachedListOfDataWrappers);
        }

        /// <summary>
        /// Override hook which allows us to also put any child 
        /// EditableValidatingViewModelBase objects into the CancelEdit state
        /// </summary>
        protected override void OnCancelEdit()
        {
            base.OnCancelEdit();
            //Now walk the list of properties in the OrderViewModel
            //and call CancelEdit() on all Cinch.DataWrapper<T>s.
            //we can use the Cinch.DataWrapperHelper class for this
            DataWrapperHelper.SetCancelEdit(cachedListOfDataWrappers);
        }
        #endregion
    }
}
